import pygame
import random
import os

# 初始化Pygame
pygame.init()

# 游戏窗口设置
SCREEN_WIDTH = 460
SCREEN_HEIGHT = 720
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("羊了个羊")

# 颜色定义
BG_COLOR = (255, 255, 255)

# 卡片尺寸和间距
CARD_WIDTH = 55
CARD_HEIGHT = 70
SPACING = 40

# 游戏区域布局
GRID_ROWS = 3
GRID_COLS = 3
grid_width = GRID_COLS * (CARD_WIDTH + SPACING) - SPACING
GRID_LEFT = (SCREEN_WIDTH - grid_width) // 2
GRID_TOP = 100

# 槽位区域设置
SLOT_ROWS = 1
SLOT_COLS = 7  # 最多存放7个卡片
slot_width = SLOT_COLS * (CARD_WIDTH + 5) - 5
SLOT_LEFT = (SCREEN_WIDTH - slot_width) // 2
SLOT_TOP = SCREEN_HEIGHT - CARD_HEIGHT - 50
SLOT_HEIGHT = CARD_HEIGHT + 20

# 道具设置
ITEM_WIDTH = 40
ITEM_HEIGHT = 60
ITEM_LEFT = SCREEN_WIDTH - ITEM_WIDTH - 390
ITEM_TOP = 60
ITEM_SPACING = 10  # 道具之间的垂直间距

# 道具数量
item_count = 1
undo_item_count = 1
shuffle_item_count = 1

# 加载背景图像
try:
    image_folder = os.path.join(os.path.dirname(__file__), "image")
    background_path1 = os.path.join(image_folder, "back.png")
    background_path2 = os.path.join(image_folder, "back1.png")
    background_img1 = pygame.image.load(background_path1)
    background_img1 = pygame.transform.scale(background_img1, (SCREEN_WIDTH, SCREEN_HEIGHT))
    background_img2 = pygame.image.load(background_path2)
    background_img2 = pygame.transform.scale(background_img2, (SCREEN_WIDTH, SCREEN_HEIGHT))
    print("主背景图像加载成功")
    # 用于切换背景的标志
    current_background = 0
    # 背景切换的时间间隔（毫秒）
    BACKGROUND_SWITCH_INTERVAL = 200
    last_switch_time = pygame.time.get_ticks()
except Exception as e:
    print(f"主背景图像加载失败: {e}")
    background_img1 = None
    background_img2 = None

# 加载槽位背景图像
try:
    slot_bg_path = os.path.join(image_folder, "back2.png")
    slot_bg_img = pygame.image.load(slot_bg_path)
    slot_bg_img = pygame.transform.scale(slot_bg_img, (slot_width + 20, SLOT_HEIGHT + 20))
    print("槽位背景图像加载成功")
except Exception as e:
    print(f"槽位背景图像加载失败: {e}")
    slot_bg_img = None

# 加载卡片图片
card_images = []
try:
    for i in range(5):
        if i == 0:
            tile_path = os.path.join(image_folder, "tile.png")
        else:
            tile_path = os.path.join(image_folder, f"tile{i}.png")

        if os.path.exists(tile_path):
            img = pygame.image.load(tile_path)
            img = pygame.transform.scale(img, (CARD_WIDTH, CARD_HEIGHT))
            card_images.append(img)
            print(f"卡片图片 {os.path.basename(tile_path)} 加载成功")
        else:
            print(f"卡片图片 {tile_path} 不存在")

    if not card_images:
        raise Exception("没有找到任何卡片图片")

except Exception as e:
    print(f"卡片图片加载失败: {e}")
    COLORS = [
        (255, 0, 0),  # 红
        (0, 255, 0),  # 绿
        (0, 0, 255),  # 蓝
        (255, 255, 0),  # 黄
        (128, 0, 128),  # 紫
    ]

# 加载mask图像
try:
    mask_path = os.path.join(image_folder, "mask.png")
    mask_img = pygame.image.load(mask_path)
    mask_img = pygame.transform.scale(mask_img, (CARD_WIDTH, CARD_HEIGHT))
    print("mask图像加载成功")
except Exception as e:
    print(f"mask图像加载失败: {e}")
    mask_img = None

# 加载道具图像
try:
    item_path = os.path.join(image_folder, "item_icon.jpg")
    item_img = pygame.image.load(item_path)
    item_img = pygame.transform.scale(item_img, (ITEM_WIDTH, ITEM_HEIGHT))
    print("道具图像加载成功")
except Exception as e:
    print(f"道具图像加载失败: {e}")
    item_img = None

# 加载撤销道具图像
try:
    undo_item_path = os.path.join(image_folder, "chexiao.webp")
    undo_item_img = pygame.image.load(undo_item_path)
    undo_item_img = pygame.transform.scale(undo_item_img, (ITEM_WIDTH, ITEM_HEIGHT))  # 使用统一尺寸
    print("撤销道具图像加载成功")
except Exception as e:
    print(f"撤销道具图像加载失败: {e}")
    undo_item_img = None

# 加载洗牌道具图像
try:
    shuffle_item_path = os.path.join(image_folder, "suiji.webp")
    shuffle_item_img = pygame.image.load(shuffle_item_path)
    shuffle_item_img = pygame.transform.scale(shuffle_item_img, (ITEM_WIDTH, ITEM_HEIGHT))  # 使用统一尺寸
    print("洗牌道具图像加载成功")
except Exception as e:
    print(f"洗牌道具图像加载失败: {e}")
    shuffle_item_img = None

# 加载粒子效果图像
try:
    particle_path = os.path.join(image_folder, "tile10.png")
    particle_img = pygame.image.load(particle_path)
    particle_img = pygame.transform.scale(particle_img, (30, 30))
    print("粒子效果图像加载成功")
except Exception as e:
    print(f"粒子效果图像加载失败: {e}")
    particle_img = None

# 游戏状态
slots = []
score = 0
game_over = False
game_won = False
moving_cards = []
particles = []
history = []  # 用于存储游戏历史状态


# 道具类 - 用于统一管理道具
class Item:
    def __init__(self, name, img, x, y, count):
        self.name = name
        self.img = img
        self.x = x
        self.y = y
        self.count = count
        self.width = ITEM_WIDTH
        self.height = ITEM_HEIGHT

    def draw(self, screen, font):
        if self.img:
            screen.blit(self.img, (self.x, self.y))
            text = font.render(f"x{self.count}", True, (255, 0, 0))
            screen.blit(text, (self.x + self.width + 5, self.y + self.height // 2 - 10))

    def is_clicked(self, pos):
        x, y = pos
        return (self.x <= x <= self.x + self.width and
                self.y <= y <= self.y + self.height)


# 创建道具实例
items = [
    Item("消除", item_img, ITEM_LEFT, ITEM_TOP, item_count),
    Item("撤销", undo_item_img, ITEM_LEFT, ITEM_TOP + ITEM_HEIGHT + ITEM_SPACING, undo_item_count),
    Item("洗牌", shuffle_item_img, ITEM_LEFT, ITEM_TOP + 2 * (ITEM_HEIGHT + ITEM_SPACING), shuffle_item_count)
]


class MovingCard:
    def __init__(self, card_type, start_x, start_y, end_x, end_y):
        self.card_type = card_type
        self.x = start_x
        self.y = start_y
        self.end_x = end_x
        self.end_y = end_y
        self.speed = 8
        self.scale = 1.5  # 点击后更大的放大比例
        self.target_scale = 1.0  # 移动过程中不小于原始尺寸
        self.scale_speed = 0.01  # 减小缩放速度

    def update(self):
        if self.x != self.end_x:
            if self.x < self.end_x:
                self.x = min(self.x + self.speed, self.end_x)
            else:
                self.x = max(self.x - self.speed, self.end_x)
        if self.y != self.end_y:
            if self.y < self.end_y:
                self.y = min(self.y + self.speed, self.end_y)
            else:
                self.y = max(self.y - self.speed, self.end_y)

        if self.scale > self.target_scale:
            self.scale = max(self.scale - self.scale_speed, self.target_scale)

        return self.x == self.end_x and self.y == self.end_y

    def draw(self):
        if card_images:
            scaled_img = pygame.transform.scale(card_images[self.card_type],
                                                (int(CARD_WIDTH * self.scale), int(CARD_HEIGHT * self.scale)))
            screen.blit(scaled_img, (self.x - (scaled_img.get_width() - CARD_WIDTH) // 2,
                                     self.y - (scaled_img.get_height() - CARD_HEIGHT) // 2))
        else:
            scaled_width = int(CARD_WIDTH * self.scale)
            scaled_height = int(CARD_HEIGHT * self.scale)
            pygame.draw.rect(screen, COLORS[self.card_type],
                             (self.x - (scaled_width - CARD_WIDTH) // 2, self.y - (scaled_height - CARD_HEIGHT) // 2,
                              scaled_width, scaled_height))


class Particle:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.speed_x = random.uniform(-5, 5)
        self.speed_y = random.uniform(-5, 5)
        self.alpha = 255

    def update(self):
        self.x += self.speed_x
        self.y += self.speed_y
        self.alpha -= 5
        if self.alpha <= 0:
            return True
        return False

    def draw(self):
        if particle_img:
            particle = particle_img.copy()
            particle.set_alpha(self.alpha)
            screen.blit(particle, (self.x - particle.get_width() // 2, self.y - particle.get_height() // 2))


def check_victory():
    """检查是否胜利"""
    for row in grid:
        for stack in row:
            if len(stack) > 0:
                return False
    return len(slots) == 0


def save_game_state():
    """保存当前游戏状态到历史记录"""
    grid_copy = [[stack.copy() for stack in row] for row in grid]
    slots_copy = slots.copy()
    score_copy = score
    history.append((grid_copy, slots_copy, score_copy))


def shuffle_grid():
    """随机洗牌功能"""
    all_cards = []
    # 收集所有卡片
    for row in grid:
        for stack in row:
            all_cards.extend(stack)
            stack.clear()

    # 打乱卡片顺序
    random.shuffle(all_cards)

    # 重新分配卡片到各个堆栈
    index = 0
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            stack_size = random.randint(1, min(7, len(all_cards) - index))
            grid[row][col] = all_cards[index:index + stack_size]
            index += stack_size

    # 如果有剩余卡片，随机添加到某些堆栈
    while index < len(all_cards):
        row = random.randint(0, GRID_ROWS - 1)
        col = random.randint(0, GRID_COLS - 1)
        grid[row][col].append(all_cards[index])
        index += 1


# 初始化卡片堆
grid = []
for row in range(GRID_ROWS):
    grid_row = []
    for col in range(GRID_COLS):
        layers = random.randint(3, 7)
        max_card_type = len(card_images) - 1 if card_images else len(COLORS) - 1
        stack = [random.randint(0, max_card_type) for _ in range(layers)]
        stack += [stack[-1]] * (3 - layers % 3) if layers % 3 != 0 else []
        grid_row.append(stack)
    grid.append(grid_row)

# 主循环
clock = pygame.time.Clock()
running = True

while running:
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN and not game_over:
            x, y = pygame.mouse.get_pos()

            # 检查是否点击道具
            for i, item in enumerate(items):
                if item.is_clicked((x, y)):
                    if item.count > 0:
                        save_game_state()
                        if i == 0:  # 消除道具
                            slots = []
                            items[0].count -= 1
                        elif i == 1:  # 撤销道具
                            if history:
                                previous_state = history.pop()
                                grid[:] = previous_state[0]
                                slots[:] = previous_state[1]
                                score = previous_state[2]
                                items[1].count -= 1
                        elif i == 2:  # 洗牌道具
                            shuffle_grid()
                            items[2].count -= 1
                        break
            else:
                # 计算点击位置
                grid_col = (x - GRID_LEFT) // (CARD_WIDTH + SPACING)
                grid_row = (y - GRID_TOP) // (CARD_HEIGHT + SPACING)
                # 检查点击范围
                if 0 <= grid_row < GRID_ROWS and 0 <= grid_col < GRID_COLS:
                    if len(grid[grid_row][grid_col]) > 0:
                        # 检查槽位是否已满
                        if len(slots) >= SLOT_COLS:
                            game_over = True
                            continue

                        # 保存当前游戏状态
                        save_game_state()

                        # 取出顶层卡片
                        card = grid[grid_row][grid_col].pop()
                        start_x = GRID_LEFT + grid_col * (CARD_WIDTH + SPACING)
                        start_y = GRID_TOP + grid_row * (CARD_HEIGHT + SPACING) + (len(grid[grid_row][grid_col])) * (
                                CARD_HEIGHT // 12)
                        end_x = SLOT_LEFT + len(slots) * (CARD_WIDTH + 5)
                        end_y = SLOT_TOP
                        moving_cards.append(MovingCard(card, start_x, start_y, end_x, end_y))

    # 检查是否需要切换背景
    current_time = pygame.time.get_ticks()
    if current_time - last_switch_time > BACKGROUND_SWITCH_INTERVAL:
        current_background = 1 - current_background
        last_switch_time = current_time

    # 绘制界面
    if background_img1 and background_img2:
        if current_background == 0:
            screen.blit(background_img1, (0, 0))
        else:
            screen.blit(background_img2, (0, 0))
    else:
        screen.fill(BG_COLOR)

    # 绘制卡片堆
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            x = GRID_LEFT + col * (CARD_WIDTH + SPACING)
            y = GRID_TOP + row * (CARD_HEIGHT + SPACING)
            stack = grid[row][col]
            for index, card_type in enumerate(stack):
                offset_y = index * (CARD_HEIGHT // 12)  # 调整重叠的偏移量
                draw_y = y + offset_y
                if card_images:
                    screen.blit(card_images[card_type], (x, draw_y))
                else:
                    pygame.draw.rect(screen, COLORS[card_type], (x, draw_y, CARD_WIDTH, CARD_HEIGHT))
                # 除了最上层卡片，其他卡片上方叠加mask图像
                if index < len(stack) - 1 and mask_img:
                    screen.blit(mask_img, (x, draw_y))

    # 绘制槽位背景
    if slot_bg_img:
        screen.blit(slot_bg_img, (SLOT_LEFT - 10, SLOT_TOP - 10))
    else:
        pygame.draw.rect(screen, (200, 200, 200),
                         (SLOT_LEFT - 5, SLOT_TOP - 5,
                          slot_width + 10, SLOT_HEIGHT + 10),
                         border_radius=10)

    # 更新并绘制移动中的卡片
    finished_cards = []
    for card in moving_cards:
        if card.update():
            finished_cards.append(card)
            slots.append(card.card_type)
        card.draw()

    # 移除已完成移动的卡片
    for card in finished_cards:
        moving_cards.remove(card)

    # 绘制槽位中已静止的卡片
    for i, card in enumerate(slots):
        x = SLOT_LEFT + i * (CARD_WIDTH + 5)
        if card_images:
            screen.blit(card_images[card], (x, SLOT_TOP))
        else:
            pygame.draw.rect(screen, COLORS[card], (x, SLOT_TOP, CARD_WIDTH, CARD_HEIGHT))

    # 检查连续三个相同卡片
    if len(slots) >= 3 and slots[-1] == slots[-2] == slots[-3]:
        del slots[-3:]
        score += 1
        for _ in range(10):
            x = SLOT_LEFT + (len(slots) + 1) * (CARD_WIDTH + 5)
            y = SLOT_TOP
            particles.append(Particle(x, y))

    # 更新并绘制粒子效果
    finished_particles = []
    for particle in particles:
        if particle.update():
            finished_particles.append(particle)
        else:
            particle.draw()

    # 移除已完成的粒子效果
    for particle in finished_particles:
        particles.remove(particle)

    # 绘制道具
    font = pygame.font.Font(None, 24)
    for item in items:
        item.draw(screen, font)

    # 绘制状态信息
    font = pygame.font.Font(None, 36)
    text = font.render(f"Score: {score}", True, (0, 0, 0))
    screen.blit(text, (20, 20))

    # 绘制槽位容量提示
    capacity_text = font.render(f"{len(slots)}/{SLOT_COLS}", True, (100, 100, 100))
    screen.blit(capacity_text, (SCREEN_WIDTH - 60, 20))

    # 检查胜利条件
    if check_victory():
        game_won = True
        game_over = True

    # 绘制游戏结束/胜利信息
    if game_over:
        text = font.render("YOU WIN!" if game_won else "GAME OVER!",
                           True, (0, 255, 0) if game_won else (255, 0, 0))
        screen.blit(text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT // 2 - 20))

    pygame.display.flip()
    clock.tick(30)

pygame.quit()